use std::{
    collections::{HashMap, VecDeque},
    sync::{Arc, Mutex},
};

use model_graph_types::{
    container::workflow::{
        ValueSelector, WorkflowBlockExecuteResult, WorkflowBlockExecuteResultBuilder,
        WorkflowBlockExecuteResultStatus, WorkflowBlockForEach, WorkflowBlockRef,
    },
    modeling::Value,
};

use crate::workflow::context::{Getter, Setter, WorkflowContext};

pub async fn execute(
    id: &String,
    block: &WorkflowBlockForEach,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<WorkflowBlockExecuteResult> {
    let result = if let Some(iterator) = &block.iterator {
        _for_execute(id, iterator, block, context).await
    } else {
        _loop_execute(id, block, context).await
    };

    match result {
        Ok(v) => Ok(WorkflowBlockExecuteResultBuilder::default()
            .status(WorkflowBlockExecuteResultStatus::Succeeded)
            .source_handle("source")
            .result(v)
            .build()?),
        Err(err) => Ok(WorkflowBlockExecuteResultBuilder::default()
            .status(WorkflowBlockExecuteResultStatus::Succeeded)
            .source_handle("fail-branch")
            .build()?),
    }
}

pub async fn _for_execute(
    id: &String,
    iterator: &ValueSelector,
    block: &WorkflowBlockForEach,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<HashMap<String, Value>> {
    //获取变量 iterator
    let iterator_value = context.get_from_node(&iterator.1, &iterator.0)?;

    let values = match iterator_value {
        Value::Array(v) => v,
        _ => vec![iterator_value],
    };

    let context_temp = context.clone();

    let result_list: Arc<Mutex<Vec<Value>>> = Arc::new(Mutex::new(vec![]));

    let result_list_temp = result_list.clone();

    Box::pin(async move {
        for (index, item) in values.iter().enumerate() {
            //设置 item 与index
            let mut item_index = HashMap::new();
            //
            item_index.insert(
                String::from("index"),
                Value::Number(index.try_into().unwrap()),
            );
            item_index.insert(String::from("item"), item.clone());
            context_temp.set_node_result(&id, item_index).unwrap();

            //获取root
            let root = block.root.clone();
            //启动
            let mut running_queue: VecDeque<WorkflowBlockRef> = VecDeque::new();
            running_queue.push_back(root);

            while !running_queue.is_empty() {
                if let Some(block) = running_queue.pop_front() {
                    let block_id = {
                        if let Ok(b) = block.clone().lock() {
                            b.id.clone()
                        } else {
                            String::new()
                        }
                    };
                    // 同步执行
                    if let Ok(block_result) =
                        crate::workflow::executor::execute(&block, context_temp.clone()).await
                    {
                        //
                        //获取outputs，并激活
                        let outputs = {
                            if let Ok(b) = block.clone().lock() {
                                b.outputs.clone()
                            } else {
                                HashMap::new()
                            }
                        };
                        for (key, value) in outputs {
                            if let Some(source_handle) = &block_result.source_handle {
                                //
                                if key.contains(source_handle) {
                                    //检测节点是否激活
                                    running_queue.push_back(value.clone());
                                }
                            } else {
                                tracing::debug!("{},{:?}", key, value);
                                //检测节点是否激活
                                running_queue.push_back(value.clone());
                            }
                        }
                        //将节点的输出，写入到context中
                        if let Err(err) =
                            context_temp.set_node_result(&block_id, block_result.result)
                        {
                            tracing::error!("{}", err);
                        }
                    } else {
                        //调用执行失败
                    }
                }
            }
            //执行完成，获取结果
            let output_selector = &block.output;
            let result = context
                .get_from_node(&output_selector.1, &output_selector.0)
                .unwrap();
            result_list_temp.lock().unwrap().push(result);
        } //end for
    })
    .await;

    tracing::debug!("迭代结束！");

    let mut outputs: HashMap<String, Value> = HashMap::new();
    let list: Vec<Value> = result_list
        .lock()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .clone();
    outputs.insert(String::from("output"), Value::Array(list));

    Ok(outputs)
}

pub async fn _loop_execute(
    id: &String,
    block: &WorkflowBlockForEach,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<HashMap<String, Value>> {
    let context_temp = context.clone();

    let result_list: Arc<Mutex<Vec<Value>>> = Arc::new(Mutex::new(vec![]));

    let result_list_temp = result_list.clone();

    Box::pin(async move {
        let mut index = 0;
        let item = Value::None;

        loop {
            //设置 item 与index
            let mut item_index = HashMap::new();
            //
            item_index.insert(
                String::from("index"),
                Value::Number(index.try_into().unwrap()),
            );
            item_index.insert(String::from("item"), item.clone());
            context_temp.set_node_result(&id, item_index).unwrap();

            //获取root
            let root = block.root.clone();
            //启动
            let mut running_queue: VecDeque<WorkflowBlockRef> = VecDeque::new();
            running_queue.push_back(root);

            while !running_queue.is_empty() {
                if let Some(block) = running_queue.pop_front() {
                    let block_id = {
                        if let Ok(b) = block.clone().lock() {
                            b.id.clone()
                        } else {
                            String::new()
                        }
                    };
                    // 同步执行
                    if let Ok(block_result) =
                        crate::workflow::executor::execute(&block, context_temp.clone()).await
                    {
                        //
                        //获取outputs，并激活
                        let outputs = {
                            if let Ok(b) = block.clone().lock() {
                                b.outputs.clone()
                            } else {
                                HashMap::new()
                            }
                        };
                        for (key, value) in outputs {
                            if let Some(source_handle) = &block_result.source_handle {
                                //
                                if key.contains(source_handle) {
                                    //检测节点是否激活
                                    running_queue.push_back(value.clone());
                                }
                            } else {
                                tracing::debug!("{},{:?}", key, value);
                                //检测节点是否激活
                                running_queue.push_back(value.clone());
                            }
                        }
                        //将节点的输出，写入到context中
                        if let Err(err) =
                            context_temp.set_node_result(&block_id, block_result.result)
                        {
                            tracing::error!("{}", err);
                        }
                    } else {
                        //调用执行失败
                    }
                }
            }
            //执行完成，获取结果
            let output_selector = &block.output;
            let result = context
                .get_from_node(&output_selector.1, &output_selector.0)
                .unwrap();
            result_list_temp.lock().unwrap().push(result);

            index = index + 1;
        } //end for
    })
    .await;

    tracing::debug!("迭代结束！");

    let mut outputs: HashMap<String, Value> = HashMap::new();
    let list: Vec<Value> = result_list
        .lock()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .clone();
    outputs.insert(String::from("output"), Value::Array(list));

    Ok(outputs)
}
